home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / libs / libelf-0.5 / libelf-0 / libelf-0.5.2 / begin.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-19  |  7.6 KB  |  314 lines

  1. /*
  2. begin.c - implementation of the elf_begin(3) function.
  3. Copyright (C) 1995 Michael Riepe <riepe@ifwsn4.ifw.uni-hannover.de>
  4.  
  5. This library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Library General Public
  7. License as published by the Free Software Foundation; either
  8. version 2 of the License, or (at your option) any later version.
  9.  
  10. This library is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13. Library General Public License for more details.
  14.  
  15. You should have received a copy of the GNU Library General Public
  16. License along with this library; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18. */
  19.  
  20. #include <private.h>
  21. #include <ar.h>
  22.  
  23. static const Elf _elf_init = INIT_ELF;
  24. static const char fmag[] = ARFMAG;
  25.  
  26. static unsigned long
  27. getnum(const char *str, size_t len, int base, int *err) {
  28.     unsigned long result = 0;
  29.  
  30.     while (len && *str == ' ') {
  31.     str++; len--;
  32.     }
  33.     while (len && *str >= '0' && (*str - '0') < base) {
  34.     result = base * result + *str++ - '0'; len--;
  35.     }
  36.     while (len && *str == ' ') {
  37.     str++; len--;
  38.     }
  39.     if (len) {
  40.     *err = len;
  41.     }
  42.     return result;
  43. }
  44.  
  45. static void
  46. _elf_init_ar(Elf *elf) {
  47.     struct ar_hdr *hdr;
  48.     size_t offset;
  49.     size_t size;
  50.     int err = 0;
  51.  
  52.     elf->e_kind = ELF_K_AR;
  53.     elf->e_idlen = SARMAG;
  54.     elf->e_off = SARMAG;
  55.     elf->e_cooked = 1;        /* do not freeze archives! */
  56.  
  57.     /* process special members */
  58.     offset = SARMAG;
  59.     while (!elf->e_strtab && offset + sizeof(*hdr) <= elf->e_size) {
  60.     hdr = (struct ar_hdr*)(elf->e_data + offset);
  61.     if (memcmp(hdr->ar_fmag, fmag, sizeof(fmag) - 1)) {
  62.         break;
  63.     }
  64.     if (hdr->ar_name[0] != '/') {
  65.         break;
  66.     }
  67.     size = getnum(hdr->ar_size, sizeof(hdr->ar_size), 10, &err);
  68.     if (err || !size) {
  69.         break;
  70.     }
  71.     offset += sizeof(*hdr);
  72.     if (offset + size > elf->e_size) {
  73.         break;
  74.     }
  75.     if (hdr->ar_name[1] == '/' && hdr->ar_name[2] == ' ') {
  76.         elf->e_strtab = elf->e_data + offset;
  77.         elf->e_strlen = size;
  78.         break;
  79.     }
  80.     if (elf->e_symtab || hdr->ar_name[1] != ' ') {
  81.         break;
  82.     }
  83.     elf->e_symtab = elf->e_data + offset;
  84.     elf->e_symlen = size;
  85.     offset += size + (size & 1);
  86.     }
  87. }
  88.  
  89. static Elf_Arhdr*
  90. _elf_arhdr(Elf *arf) {
  91.     struct ar_hdr *hdr;
  92.     Elf_Arhdr *arhdr;
  93.     size_t namelen;
  94.     size_t tmp;
  95.     char *name;
  96.     int err = 0;
  97.  
  98.     if (arf->e_off == arf->e_size) {
  99.     /* no error! */
  100.     return NULL;
  101.     }
  102.     if (arf->e_off < 0 || arf->e_off > arf->e_size) {
  103.     seterr(ERROR_OUTSIDE);
  104.     return NULL;
  105.     }
  106.     if (arf->e_off + sizeof(*hdr) > arf->e_size) {
  107.     seterr(ERROR_TRUNC_ARHDR);
  108.     return NULL;
  109.     }
  110.     elf_assert(arf->e_data != NULL);
  111.     hdr = (struct ar_hdr*)(arf->e_data + arf->e_off);
  112.     if (memcmp(hdr->ar_fmag, fmag, sizeof(fmag) - 1)) {
  113.     seterr(ERROR_ARFMAG);
  114.     return NULL;
  115.     }
  116.  
  117.     name = hdr->ar_name;
  118.     for (namelen = sizeof(hdr->ar_name); namelen > 0; namelen--) {
  119.     if (name[namelen - 1] != ' ') {
  120.         break;
  121.     }
  122.     }
  123.     if (name[0] == '/') {
  124.     if (name[1] >= '0' && name[1] <= '9') {
  125.         if (!arf->e_strtab) {
  126.         seterr(ERROR_ARSTRTAB);
  127.         return NULL;
  128.         }
  129.         tmp = getnum(&name[1], namelen - 1, 10, &err);
  130.         if (err) {
  131.         seterr(ERROR_ARSPECIAL);
  132.         return NULL;
  133.         }
  134.         if (tmp < 0 || tmp >= arf->e_strlen) {
  135.         seterr(ERROR_ARSTRTAB);
  136.         return NULL;
  137.         }
  138.         name = arf->e_strtab + tmp;
  139.         for (namelen = tmp; namelen < arf->e_strlen; namelen++) {
  140.         if (name[namelen] == '/') {
  141.             namelen -= tmp;
  142.             break;
  143.         }
  144.         }
  145.         if (namelen == arf->e_strlen) {
  146.         seterr(ERROR_ARSTRTAB);
  147.         return NULL;
  148.         }
  149.     }
  150.     else if (namelen != 1 && !(namelen == 2 && name[1] == '/')) {
  151.         seterr(ERROR_ARSPECIAL);
  152.         return NULL;
  153.     }
  154.     }
  155.     else if (namelen > 0 && name[namelen - 1] == '/') {
  156.     namelen--;
  157.     }
  158.     else {
  159.     namelen = 0;
  160.     }
  161.  
  162.     if (!(arhdr = (Elf_Arhdr*)malloc(sizeof(*arhdr) +
  163.              sizeof(hdr->ar_name) + namelen + 2))) {
  164.     seterr(ERROR_MEM_ARHDR);
  165.     return NULL;
  166.     }
  167.  
  168.     arhdr->ar_name = NULL;
  169.     arhdr->ar_rawname = (char*)(arhdr + 1);
  170.     arhdr->ar_date = getnum(hdr->ar_date, sizeof(hdr->ar_date), 10, &err);
  171.     arhdr->ar_uid = getnum(hdr->ar_uid, sizeof(hdr->ar_uid), 10, &err);
  172.     arhdr->ar_gid = getnum(hdr->ar_gid, sizeof(hdr->ar_gid), 10, &err);
  173.     arhdr->ar_mode = getnum(hdr->ar_mode, sizeof(hdr->ar_mode), 8, &err);
  174.     arhdr->ar_size = getnum(hdr->ar_size, sizeof(hdr->ar_size), 10, &err);
  175.     if (err) {
  176.     free(arhdr);
  177.     seterr(ERROR_ARHDR);
  178.     return NULL;
  179.     }
  180.  
  181.     memcpy(arhdr->ar_rawname, hdr->ar_name, sizeof(hdr->ar_name));
  182.     arhdr->ar_rawname[sizeof(hdr->ar_name)] = '\0';
  183.  
  184.     if (namelen) {
  185.     arhdr->ar_name = arhdr->ar_rawname + sizeof(hdr->ar_name) + 1;
  186.     memcpy(arhdr->ar_name, name, namelen);
  187.     arhdr->ar_name[namelen] = '\0';
  188.     }
  189.  
  190.     return arhdr;
  191. }
  192.  
  193. Elf*
  194. elf_begin(int fd, Elf_Cmd cmd, Elf *ref) {
  195.     Elf_Arhdr *arhdr = NULL;
  196.     size_t size = 0;
  197.     Elf *elf;
  198.  
  199.     elf_assert(_elf_init.e_magic == ELF_MAGIC);
  200.     if (_elf_version == EV_NONE) {
  201.     seterr(ERROR_VERSION_UNSET);
  202.     return NULL;
  203.     }
  204.     else if (cmd == ELF_C_NULL) {
  205.     return NULL;
  206.     }
  207.     else if (cmd == ELF_C_WRITE) {
  208.     ref = NULL;
  209.     }
  210.     else if (cmd != ELF_C_READ && cmd != ELF_C_RDWR) {
  211.     seterr(ERROR_INVALID_CMD);
  212.     return NULL;
  213.     }
  214.     else if (ref) {
  215.     elf_assert(ref->e_magic == ELF_MAGIC);
  216.     if (!ref->e_readable || (cmd == ELF_C_RDWR && !ref->e_writable)) {
  217.         seterr(ERROR_CMDMISMATCH);
  218.         return NULL;
  219.     }
  220.     if (ref->e_kind != ELF_K_AR) {
  221.         ref->e_count++;
  222.         return ref;
  223.     }
  224.     if (cmd == ELF_C_RDWR) {
  225.         seterr(ERROR_MEMBERWRITE);
  226.         return NULL;
  227.     }
  228.     if (fd != ref->e_fd) {
  229.         seterr(ERROR_FDMISMATCH);
  230.         return NULL;
  231.     }
  232.     if (!(arhdr = _elf_arhdr(ref))) {
  233.         return NULL;
  234.     }
  235.     size = arhdr->ar_size;
  236.     }
  237.     else if ((size = lseek(fd, 0L, 2)) == (size_t)-1L) {
  238.     seterr(ERROR_IO_GETSIZE);
  239.     return NULL;
  240.     }
  241.  
  242.     if (!(elf = (Elf*)malloc(sizeof(Elf)))) {
  243.     seterr(ERROR_MEM_ELF);
  244.     return NULL;
  245.     }
  246.     *elf = _elf_init;
  247.     elf->e_fd = fd;
  248.     elf->e_parent = ref;
  249.     elf->e_size = size;
  250.  
  251.     if (cmd != ELF_C_READ) {
  252.     elf->e_writable = 1;
  253.     }
  254.     if (cmd != ELF_C_WRITE) {
  255.     elf->e_readable = 1;
  256.     }
  257.     else {
  258.     return elf;
  259.     }
  260.  
  261.     if (ref) {
  262.     size_t offset = ref->e_off + sizeof(struct ar_hdr);
  263.     Elf *xelf;
  264.  
  265.     elf_assert(arhdr);
  266.     elf->e_arhdr = arhdr;
  267.     elf->e_base = ref->e_base + offset;
  268.     /*
  269.      * Share the archive's memory image. To avoid
  270.      * multiple independent elf descriptors if the
  271.      * same member is requested twice, scan the list
  272.      * of open members for duplicates.
  273.      *
  274.      * I don't know how SVR4 handles this case. Don't rely on it.
  275.      */
  276.     for (xelf = ref->e_members; xelf; xelf = xelf->e_link) {
  277.         elf_assert(xelf->e_parent == ref);
  278.         if (xelf->e_base == elf->e_base) {
  279.         free(arhdr);
  280.         free(elf);
  281.         xelf->e_count++;
  282.         return xelf;
  283.         }
  284.     }
  285.     elf->e_data = size ? ref->e_data + offset : (char*)NULL;
  286.     elf->e_next = offset + size + (size & 1);
  287.     elf->e_disabled = ref->e_disabled;
  288.     /* parent/child linking */
  289.     elf->e_link = ref->e_members;
  290.     ref->e_members = elf;
  291.     ref->e_count++;
  292.     /* Slowaris compatibility - do not rely on this! */
  293.     ref->e_off = elf->e_next;
  294.     }
  295.     else if (size && !(elf->e_data = _elf_read(elf, NULL, 0, size))) {
  296.     free(elf);
  297.     return NULL;
  298.     }
  299.  
  300.     elf->e_idlen = size;
  301.     if (size >= EI_NIDENT && !memcmp(elf->e_data, ELFMAG, SELFMAG)) {
  302.     elf->e_kind = ELF_K_ELF;
  303.     elf->e_idlen = EI_NIDENT;
  304.     elf->e_class = elf->e_data[EI_CLASS];
  305.     elf->e_encoding = elf->e_data[EI_DATA];
  306.     elf->e_version = elf->e_data[EI_VERSION];
  307.     }
  308.     else if (size >= SARMAG && !memcmp(elf->e_data, ARMAG, SARMAG)) {
  309.     _elf_init_ar(elf);
  310.     }
  311.  
  312.     return elf;
  313. }
  314.